﻿using System;
using System.IO;
using Microsoft.SharePoint;
using Microsoft.SharePoint.Deployment;

namespace SKN
{
    /// <summary>
    /// Contains common method for Migration
    /// </summary>
    public static class Migration
    {
        /// <summary>
        /// Use this method to archieve documents from a given document library to file share
        /// </summary>
        /// <param name="web"></param>
        /// <param name="documentLibraryName"></param>
        /// <param name="transferLocation"></param>
        public static void ArchieveDocuments(SPWeb web, string documentLibraryName, string transferLocation)
        {
            SPFile doc;
            SPListItemCollection listItems = web.Lists[documentLibraryName].Items;

            foreach (SPListItem listItem in listItems)
            {
                doc = listItem.File;
                string path = "";
                byte[] buffer = doc.OpenBinary();
                if (transferLocation.EndsWith(@"\"))
                {
                    path += doc.Name;
                }
                else
                {
                    path += @"\" + doc.Name;
                }

                var fs = new FileStream(path, FileMode.Create);
                fs.Write(buffer, 0, buffer.Length);
                fs.Flush();
                fs.Close();
            }
        }

        /// <summary>
        /// Use this method to export documents from a document library with all versions to file share using Content Deployment 
        /// </summary>
        /// <param name="web"></param>
        /// <param name="documentLibraryName"></param>
        /// <param name="transferLocation"></param>
        public static void ExportItems(SPWeb web, string documentLibraryName, string transferLocation)
        {
            string webUrl = web.Title;
            SPList list = web.Lists[documentLibraryName];
            SPListItemCollection listItemCollection = list.Items;

            // Set the export settings.  
            var exportSettings = new SPExportSettings
                                     {
                                         ExportMethod = SPExportMethodType.ExportAll,
                                         IncludeSecurity = SPIncludeSecurity.All,
                                         IncludeVersions = SPIncludeVersions.All
                                     };

            foreach (SPListItem listItem in listItemCollection)
            {
                var exportObject = new SPExportObject
                                       {
                                           Type = SPDeploymentObjectType.ListItem,
                                           Url = webUrl + "/" + listItem.Url
                                       };

                exportSettings.AutoGenerateDataFileName = false;
                exportSettings.BaseFileName = listItem.Name + ".cab";
                exportSettings.SiteUrl = webUrl;
                exportSettings.FileLocation = transferLocation;
                exportSettings.ExportObjects.Add(exportObject);
            }

            // Export the record.  
            var export = new SPExport(exportSettings);
            export.Run();
        }

        /// <summary>
        /// Use this method to copy file from one document library to another
        /// </summary>
        /// <param name="web"></param>
        /// <param name="srcFileUrl"></param>
        /// <param name="destFileUrl"></param>
        public static void CopyFile(SPWeb web, string srcFileUrl, string destFileUrl)
        {
            if (File.Exists(srcFileUrl) && !File.Exists(destFileUrl))
            {
                FileStream fStream = File.OpenRead(srcFileUrl);

                //Read the stream into a byte[]
                //byte[] contents = new byte[fStream.Length];
                //fStream.Read(contents, 0, (int)fStream.Length);

                //Read the stream into a byte[]
                //If you review System.IO.FileStream.Read(), the remarks section states: 
                //"An implementation is free to return fewer bytes than requested 
                //even if the end of the stream has not been reached."
                //You have to use the standard while loop. 
                var contents = new byte[fStream.Length];
                var numBytesToRead = (int) fStream.Length;
                int numBytesRead = 0;
                while (numBytesToRead > 0)
                {
                    // Read may return anything from 0 to numBytesToRead.
                    int n = fStream.Read(contents, numBytesRead, numBytesToRead);
                    // The end of the file is reached.
                    if (n == 0)
                        break;
                    numBytesRead += n;
                    numBytesToRead -= n;
                }

                fStream.Close();
                EnsureParentFolder(web, destFileUrl);
                web.Files.Add(destFileUrl, contents);

                //SPFile file = web.Files.Add(destFileUrl, contents);
                //SPListItem item = file.Item;
                //item["Author"] = "SPCore";
                //item.Update();

                web.Update();
            }
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="web"></param>
        /// <param name="srcFileUrl"></param>
        public static void FileMetadata(SPWeb web, string srcFileUrl)
        {
            throw new NotImplementedException();
        }


        private static string EnsureParentFolder(SPWeb parentSite, string destinUrl)
        {
            try
            {
                destinUrl = parentSite.GetFile(destinUrl).Url;

                int index = destinUrl.LastIndexOf("/");
                string parentFolderUrl = string.Empty;

                if (index > -1)
                {
                    parentFolderUrl = destinUrl.Substring(0, index);

                    SPFolder parentFolder
                        = parentSite.GetFolder(parentFolderUrl);

                    if (!parentFolder.Exists)
                    {
                        SPFolder currentFolder = parentSite.RootFolder;

                        foreach (string folder in parentFolderUrl.Split('/'))
                        {
                            currentFolder
                                = currentFolder.SubFolders.Add(folder);
                        }
                    }
                }
                return parentFolderUrl;
            }
            catch
            {
                //string.Format("Unable to EnsureParentFolder() on parentSite={0} and destinUrl={1}", parentSite, destinUrl);
                return string.Empty;
            }
        }
    }
}